/*******************************************************************************
 *
 * Set of macros used as API to logging framework
 *
 ******************************************************************************/

#ifndef TRACE_H
#define TRACE_H

enum traceGroup_e
{
  INFO_GROUP = 0,    //  0
  TRACE1_GROUP,      //  1
  TRACE2_GROUP,      //  2
  TRACE3_GROUP,      //  3
  TRACE4_GROUP,      //  4
  TRACE5_GROUP,      //  5
  TRACE6_GROUP,      //  6
  TRACE7_GROUP,      //  7
  TRACE8_GROUP,      //  8
  TRACE9_GROUP,      //  9
  ERROR_GROUP,       // 10
  ENTER_GROUP,       // 11
  RETURN_GROUP,      // 12
  STATE_CHANGE_GROUP,// 13
  TRACE_PARAM_GROUP, // 14
  TRACE_ERROR_GROUP, // 15
  BUS_SEND_GROUP,    // 16
  BUS_RECEIVE_GROUP, // 17
  SIG_SEND_GROUP,    // 18
  SIG_RECEIVE_GROUP, // 19
// last element
  END_GROUP
};

#include "TraceManager.h"
#include "TraceMacros.h"

/*******************************************************************************
 *
 * Macro generates a C-string form a formated string and various number of
 * arguments.
 *
 * usage: STR("Formated string that can use %s, 0x%04X and etc.",
 *              some_string_var,
 *              some_integer_var);
 *
 ******************************************************************************/
#define STR(FORMAT, ARGS...)\
  INST->doStr(FORMAT, ##ARGS)

/*******************************************************************************
 *
 * Macro that creates new TraceObject with it's unique set of trace groups
 * which can be independently enabled/disabled
 *
 * usage: DECLARE_TRACE_OBJ(MY_OWN_TRACE_OBJECT);
 *
 ******************************************************************************/
#define DECLARE_TRACE_OBJ(TRACE_OBJ_NAME)\
do{\
  INST->declareTraceObj( STRINGIFY(TRACE_OBJ_NAME) );\
}while(0)

/*******************************************************************************
 *
 * Macro that sets the process name that will appear in trace message.
 * Default value is "process_name".
 *
 * usage: TRACE_PROCESS("my_process_name");
 *
 ******************************************************************************/
#define TRACE_PROCESS(PROC_NAME)\
do{\
  INST->setProcessName(PROC_NAME);\
}while(0)

/*******************************************************************************
 *
 * Macro that sets the trace output to file.
 * By default tracing is done to stderr
 *
 * usage: TRACE_TO_FILE("trace_file.log");
 *
 ******************************************************************************/
#define TRACE_TO_FILE(TRACE_FILE)\
  INST->setTraceToFile(TRACE_FILE);

/*******************************************************************************
 *
 * Macro that sets the trace output to stderr.
 *
 * usage: TRACE_TO_STDERR();
 *
 ******************************************************************************/
#define TRACE_TO_STDERR()\
  INST->setTraceToStderr();

/*******************************************************************************
 *
 * Macro that sets the trace output to stderr.
 *
 * usage: TRACE_TO_STDOUT();
 *
 ******************************************************************************/
#define TRACE_TO_STDOUT()\
  INST->setTraceToStdout();

/*******************************************************************************
 *
 * Macro enables a trace group
 *
 * usage: ENABLE_TRACE(TRACE3);
 *        ENABLE_TRACE(ENTER);
 *
 ******************************************************************************/
#define ENABLE_TRACE(GROUP_NAME)\
  INST->enableTrace(GROUP_NAME ## _GROUP);

/*******************************************************************************
 *
 * Macro enables all trace groups
 *
 * usage: ENABLE_ALL_TRACE();
 *
 ******************************************************************************/
#define ENABLE_ALL_TRACE()\
  INST->enableAllTrace();

/*******************************************************************************
 *
 * Macro disables a trace group
 *
 * usage: DISABLE_TRACE(TRACE1);
 *        DISABLE_TRACE(INFO);
 *
 ******************************************************************************/
#define DISABLE_TRACE(GROUP_NAME)\
  INST->disableTrace(GROUP_NAME ## _GROUP);

/*******************************************************************************
 *
 * Macro disables all trace groups
 *
 * usage: ENABLE_ALL_TRACE();
 *
 ******************************************************************************/
#define DISABLE_ALL_TRACE()\
  INST->disableAllTrace();


/*******************************************************************************
 *
 * Macro enables a trace group for specified trace object
 *
 * usage: ENABLE_TRACE_OBJ(MY_OWN_TRACE_OBJECT, TRACE3);
 *        ENABLE_TRACE_OBJ(MY_OWN_TRACE_OBJECT, ENTER);
 *
 ******************************************************************************/
#define ENABLE_TRACE_OBJ(OBJ, GROUP_NAME)\
  INST->enableTraceObj(STRINGIFY(OBJ), GROUP_NAME ## _GROUP);

/*******************************************************************************
 *
 * Macro enables all trace groups for specified trace object
 *
 * usage: ENABLE_ALL_TRACE_OBJ(MY_OWN_TRACE_OBJECT);
 *
 ******************************************************************************/
#define ENABLE_ALL_TRACE_OBJ(OBJ)\
  INST->enableAllTraceObj(STRINGIFY(OBJ));

/*******************************************************************************
 *
 * Macro disables all trace groups for specified trace object
 *
 * usage: DISABLE_ALL_TRACE_OBJ(MY_OWN_TRACE_OBJECT);
 *
 ******************************************************************************/
#define DISABLE_ALL_TRACE_OBJ(OBJ)\
  INST->disableAllTraceObj(STRINGIFY(OBJ));


/*******************************************************************************
 *
 * Macro disbales a trace group for specified trace object
 *
 * usage: DISABLE_TRACE_OBJ(MY_OWN_TRACE_OBJECT, TRACE3);
 *        DISABLE_TRACE_OBJ(MY_OWN_TRACE_OBJECT, ENTER);
 *
 ******************************************************************************/
#define DISABLE_TRACE_OBJ(OBJ, GROUP_NAME)\
  INST->disableTraceObj(STRINGIFY(OBJ), GROUP_NAME ## _GROUP);

/*******************************************************************************
 *
 * Create INFO trace.
 *
 * usage: INFO("Hi this is informative trace");
 *
 ******************************************************************************/
#define INFO(FORMAT, ARGS...)\
  TRACE_CHECK_AND_CALL(INFO, FORMAT, ##ARGS)

/*******************************************************************************
 *
 * Create ENTER trace
 *
 * usage:
 *
 ******************************************************************************/
#define ENTER(FORMAT, ARGS...)\
  TRACE_CHECK_AND_CALL(ENTER, FORMAT, ##ARGS)

/*******************************************************************************
 *
 * Create RETURN trace and return from function, a return value may be added
 *
 * usage: RETURN;
 *        RETURN(true);
 *        RETURN(some_pointer->function_that_returnes_something());
 *
 ******************************************************************************/
#define RETURN\
  TRACE_CHECK_AND_CALL(RETURN, "Returning from %s", __FUNCTION__ );\
  return

/*******************************************************************************
 *
 * Create STATE_CHANGE trace
 *
 * usage: STATE_CHANGE("State machine changed state to: %s.",
 *                      state_machine_p->state_name());
 *
 ******************************************************************************/
#define STATE_CHANGE(FORMAT, ARGS...)\
  TRACE_CHECK_AND_CALL(STATE_CHANGE, FORMAT, ##ARGS)

/*******************************************************************************
 *
 * Create TRACE_PARAM trace
 *
 * usage: TRACE_PARAM("ClassName::function(%d, %u, %s)", aInt, aUInt, aString);
 *
 ******************************************************************************/
#define TRACE_PARAM(FORMAT, ARGS...)\
  TRACE_CHECK_AND_CALL(TRACE_PARAM, FORMAT, ##ARGS)


/*******************************************************************************
 *
 * Create TRACE_ERROR trace
 *
 * usage: TRACE_ERROR("Pay attention some thing went wrong, but I can handle it.");
 *
 ******************************************************************************/
#define TRACE_ERROR(FORMAT, ARGS...)\
  TRACE_CHECK_AND_CALL(TRACE_ERROR, FORMAT, ##ARGS)


/*******************************************************************************
 *
 * Create TRACE trace of level 1 to 9.
 *
 * usage: TRACE(1, "Exception.");
 *        TRACE(2, "Timer information.");
 *        TRACE(3, "General information.");
 *        TRACE(4, "This is a level 4 trace for variable=%u.", variable);
 *
 ******************************************************************************/
#define TRACE(NUM, FORMAT, ARGS...)\
  TRACE_CHECK_AND_CALL(TRACE ## NUM, FORMAT, ##ARGS)\


/*******************************************************************************
 *
 * Create BUS_SEND trace
 *
 * usage: TRACE_BUS_SEND(data_p, dataSize, "Sending message form %s", description)
 *
 ******************************************************************************/
#define TRACE_BUS_SEND(DATA, SIZE, FORMAT, ARGS...)\
  TRACE_CHECK_AND_BUS(BUS_SEND, DATA, SIZE, FORMAT, ##ARGS)

/*******************************************************************************
 *
 * Create BUS_RECEIVE trace
 *
 * usage: TRACE_BUS_RECEIVE(data_p, dataSize, "Received message form %s", description);
 *
 ******************************************************************************/
#define TRACE_BUS_RECEIVE(DATA, SIZE, FORMAT, ARGS...)\
  TRACE_CHECK_AND_BUS(BUS_RECEIVE, DATA, SIZE, FORMAT, ##ARGS)


/*******************************************************************************
 *
 * Prints TRACE trace of level 1 to 9 for specified trace object
 *
 * usage: TRACE_OBJ(MY_OWN_TRACE_OBJECT, 1, "Exception.");
 *        TRACE_OBJ(MY_OWN_TRACE_OBJECT, 2, "Timer information.");
 *        TRACE_OBJ(MY_OWN_TRACE_OBJECT, 3, "General information.");
 *        TRACE_OBJ(MY_OWN_TRACE_OBJECT, 4, "This is a level 4 trace for variable=%u.", variable);
 *
 ******************************************************************************/
#define TRACE_OBJ(TRACE_OBJ, NUM, FORMAT, ARGS...)\
  TRACE_OBJ_CHECK_AND_CALL(TRACE_OBJ, TRACE ## NUM, FORMAT, ##ARGS)\


/*******************************************************************************
 *
 * Prints TRACE trace of level 1 to 9 for specified trace object.
 * Specified MSG argument is passed directly into output stream
 *
 * usage: TRACE_OBJ(MY_OWN_TRACE_OBJECT, 1, "Exception.");
 *        TRACE_OBJ(MY_OWN_TRACE_OBJECT, 2, "Timer information. Timer=" << aTimerInstance);
 *
 ******************************************************************************/
#define TRACE_STREAM_OBJ(TRACE_OBJ, NUM, MSG)\
  TRACE_OBJ_CHECK_AND_STREAM(TRACE_OBJ, TRACE ## NUM, MSG)\

#endif // TRACE_H
